import logging

from django.db import connection

from app.decorator import jwt_auth
from app.service import inventory, goods, goods_class, cashier_admin, warehouse
from libs import time_helper, common, str_helper
from libs.common import success, error
from libs.db import DB
from libs.form import RawJsonForm

logger = logging.getLogger(__name__)


@jwt_auth
def create_inventory(request, auth):
    try:
        form = RawJsonForm(request.body)
        shop_id = auth.get('shop_id')
        cashier_id = auth.get('cashier_id')
        name = form.get('name')
        typ = form.get_int('type')
        if name == '':
            return error('无效的盘点名称')
        if typ not in [1, 2]:
            return error('无效的盘点方式')

        with connection.cursor() as cursor:
            db_admin = cashier_admin.get_admin_by_id(cursor, cashier_id, ['role_id', 'w_id'])
            role_id = db_admin.get('role_id', 0)
            valid_role_id_arr = [1, 2, 3]
            if role_id not in valid_role_id_arr:
                return error('当前角色无法盘点')
            w_id = db_admin.get('w_id', 0)
            goods_num = goods.count_shop_goods_num(cursor, shop_id)
            if role_id == 2:
                if w_id == 0:
                    return error('当前仓库管理员未设置所属仓库')
                sto_typ = 2
                should_num = goods_num
            else:
                sto_typ = 1
                round_sn = inventory.get_round_sn(shop_id)
                dh = DB('table_inventory_detail', conn=cursor)
                inv_num = dh.count({'round_sn': round_sn})
                should_num = goods_num - inv_num
            time_str = time_helper.ts_to_time_str()
            sn = inventory.get_inventory_sn(cursor)
            data = {
                'sto_typ': sto_typ,
                'i_sn': sn,
                'name': name,
                'add_time': time_str,
                'shop_id': shop_id,
                'w_id': w_id,
                'add_user': cashier_id,
                'type': typ,
                'status': 0,
                'step': 1,
                'should_num': should_num,
            }
            dh = DB('table_inventory', conn=cursor)
            data_id, _ = dh.insert(data)
            if data_id == 0:
                if dh.is_duplicate:
                    return error('盘点名称已存在')
                else:
                    return error('创建盘点失败')
            data.update({'id': data_id})
    except Exception as e:
        err = '创建盘点异常'
        print(err, e)
        return error(err)
    return success(data)


@jwt_auth
def inventory_goods_list(request, auth):
    try:
        rows = []
        form = RawJsonForm(request.body)
        post_page = form.get_int('page')
        shop_id = auth.get('shop_id')
        inventory_id = form.get('id')
        resp_params = {}
        flag = form.get_int('flag', None)
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            inventory_fields = ['id', 'sto_typ', 'add_time', 'type', 'w_id']
            db_inventory = dh.one(inventory_fields, {'id': inventory_id, 'shop_id': shop_id})
            db_inventory_id = db_inventory.get('id', 0)
            if db_inventory_id == 0:
                return error('盘点单不存在')
            count_sql, sql, bindings = inventory.build_query_inventory_goods_sql(form, shop_id, flag, db_inventory)
            total = 0
            count_rows = dh.query(count_sql, bindings)
            if len(count_rows) > 0:
                total = count_rows[0].get('num')
            resp_params.update({'total': total})
            if total > 0:
                if post_page > 0:
                    page = form.get_page()
                    sql += page.get_limit()
                    resp_params.update({'page': page.page, 'size': page.size})
                rows = dh.query(sql, bindings)
                if db_inventory.get('sto_typ') == 1:
                    goods_id_arr = []
                    for row in rows:
                        goods_id = row.get('goods_id')
                        goods_id_arr.append(str(goods_id))
                    goods_ids = ','.join(goods_id_arr)
                    if goods_ids != '':
                        img_dict = goods.query_goods_img_by_ids(goods_id_arr, cursor)
                        for row in rows:
                            goods_id = row.get('goods_id')
                            goods_id_arr.append(goods_id)
                            goods_img = img_dict.get(goods_id, '')
                            row.update({'goods_img': goods_img})
    except Exception as e:
        err = '获取盘点商品列表异常'
        print(err, e)
        return error(err)
    return success(rows, **resp_params)


@jwt_auth
def inventory_info(request, auth):
    try:
        form = RawJsonForm(request.body)
        cashier_id = auth.get('cashier_id')
        inventory_id = form.get_int('id')
        if inventory_id == 0:
            return error('无效的盘点ID')
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            filters = {'id': inventory_id, 'add_user': cashier_id}
            row = dh.one('*', filters)
    except Exception as e:
        err = '获取盘点列表异常'
        print(err, e)
        return error(err)
    return success(row)


@jwt_auth
def inventory_list(request, auth):
    try:
        form = RawJsonForm(request.body)
        cashier_id = auth.get('cashier_id')
        inventory_id = form.get_int('id')
        inventory_typ = form.get_int('type', None)
        page = form.get_page()
        rows = []
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            filters = {'add_user': cashier_id, 'status!=5': None}
            if inventory_typ is not None:
                filters.update({'type': inventory_typ})
            if inventory_id > 0:
                filters.update({'id': inventory_id})
            total = dh.count(filters)
            if total > 0:
                rows = dh.page(page).find('*', filters)
        resp_params = {'page': page.page, 'size': page.size, 'total': total}
    except Exception as e:
        err = '获取盘点列表异常'
        print(err, e)
        return error(err)
    return success(rows, **resp_params)


@jwt_auth
def save_inventory_detail(request, auth):
    try:
        form = RawJsonForm(request.body)
        shop_id = auth.get('shop_id')
        inventory_id = form.get('inventory_id')
        if inventory_id == 0:
            return error('无效的盘点ID')
        goods_id = form.get_int('goods_id')
        if goods_id == 0:
            return error('无效的商品ID')
        actual_count = form.get_dec('actual_count')
        flag = form.get_int('flag')
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            inventory_fields = ['id', 'sto_typ', 'type', 'w_id']
            db_inventory = dh.one(inventory_fields, {'id': inventory_id})
            db_inventory_id = db_inventory.get('id', 0)
            if db_inventory_id == 0:
                return error('盘点单不存在')
            db_inventory_w_id = db_inventory.get('w_id')
            db_inventory_sto_typ = db_inventory.get('sto_typ')
            db_inventory_typ = db_inventory.get('type')
            dh = DB('table_inventory_detail', conn=cursor)
            inventory_detail_fields = ['id', 'good_price', 'should_count', 'should_money', 'check_status']
            db_inventory_detail = dh.one(inventory_detail_fields, {'i_id': inventory_id, 'good_id': goods_id})
            db_inventory_detail_id = db_inventory_detail.get('id', 0)
            if flag == 1:
                if db_inventory_detail_id == 0:
                    return error('盘点商品不存在')
                affected, err = dh.delete('id=%s', [db_inventory_detail_id])
                if err is not None:
                    return error(err)
                if affected == 0:
                    return error('盘点商品删除失败')
            else:
                if db_inventory_detail_id > 0:
                    db_inventory_check_status = db_inventory_detail.get('check_status')
                    if db_inventory_check_status in [1, 2]:
                        status_dict = {1: '审核中', 2: '已通过'}
                        return error('当前状态“{}”，无法修改盘点数量'.format(status_dict.get(db_inventory_check_status)))
                    db_inventory_should_count = db_inventory_detail.get('should_count')
                    db_inventory_should_money = db_inventory_detail.get('should_money')
                    db_inventory_goods_price = db_inventory_detail.get('good_price')
                    actual_money = db_inventory_goods_price * actual_count
                    pal_count = actual_count - db_inventory_should_count
                    pal_money = actual_money - db_inventory_should_money
                    state = inventory.get_inventory_detail_state(pal_count)
                    data = {
                        'actual_count': actual_count,
                        'actual_money': actual_money,
                        'pal_count': pal_count,
                        'pal_money': pal_money,
                        'state': state,
                    }
                    if db_inventory_check_status == 3:
                        data.update({'check_status': 0})
                    dh.update(data, {'id': db_inventory_detail_id})
                else:
                    if db_inventory_sto_typ == 2:
                        goods_dh = DB('table_warehouse_goods', conn=cursor)
                        goods_fields = ['id', 'cid', 'good_count', 'good_price', 'good_cost']
                        db_goods = goods_dh.one(goods_fields, 'id=%s and w_id=%s', [goods_id, db_inventory_w_id])
                        db_goods_id = db_goods.get('id', 0)
                        if db_goods_id == 0:
                            return error('仓库商品不存在')
                        class_id = db_goods.get('cid')
                        goods_price = db_goods.get('good_price')
                        cost_price = db_goods.get('good_cost')
                        should_count = db_goods.get('good_count')
                    else:
                        goods_dh = DB('table_goods', conn=cursor)
                        goods_fields = ['id', 'class_id', 'scount', 'usdt_price', 'cost_price']
                        db_goods = goods_dh.one(goods_fields, 'id=%s and shoper_id=%s', [goods_id, shop_id])
                        db_goods_id = db_goods.get('id', 0)
                        if db_goods_id == 0:
                            return error('店铺商品不存在')
                        class_id = db_goods.get('class_id')
                        goods_price = common.to_dec(db_goods.get('usdt_price'))
                        cost_price = db_goods.get('cost_price')
                        should_count = db_goods.get('scount')
                    should_money = should_count * goods_price
                    actual_money = actual_count * goods_price
                    pal_count = actual_count - should_count
                    pal_money = actual_money - should_money
                    state = inventory.get_inventory_detail_state(pal_count)
                    if db_inventory_typ == 1:
                        round_sn = inventory.get_round_sn(shop_id)
                    else:
                        round_sn = ''
                    data = {
                        'i_id': inventory_id,
                        'good_id': goods_id,
                        'class_id': class_id,
                        'good_price': goods_price,
                        'good_cost': cost_price,
                        'should_count': should_count,
                        'should_money': should_money,
                        'actual_count': actual_count,
                        'actual_money': actual_money,
                        'pal_count': pal_count,
                        'pal_money': pal_money,
                        'state': state,
                        'round_sn': round_sn
                    }
                    dh.insert(data)
    except Exception as e:
        err = '保存盘点商品异常'
        print(err, e)
        return error(err)
    return success()


@jwt_auth
def save_inventory_detail_v2(request, auth):
    form = RawJsonForm(request.body)
    shop_id = auth.get('shop_id')
    post_args = form.get_list('')
    err_num = 0
    suc_num = 0
    with connection.cursor() as cursor:
        errs = []
        for i, post_arg in enumerate(post_args):
            action_typ, row_id, err = inventory.save_inventory_data(shop_id, post_arg, cursor)
            if err is not None:
                err_num += 1
                logger.info(action_typ, row_id, err)
                errs.append({'row_num': i + 1, 'err': err})
            else:
                suc_num += 1
    if err_num > 0:
        return error('存在提交失败的数据', err_num=err_num, suc_num=suc_num, errs=errs)
    else:
        return success(err_num=err_num, suc_num=suc_num, errs=errs)


@jwt_auth
def submit_inventory(request, auth):
    try:
        form = RawJsonForm(request.body)
        shop_id = auth.get('shop_id')
        cashier_id = auth.get('cashier_id')
        inventory_id = form.get_int('id')
        if inventory_id == 0:
            return error('无效的盘点ID')
        step = form.get_int('step')
        valid_steps = [1, 2, 3]
        if step not in valid_steps:
            return error('无效的盘点阶段')
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            db_inventory = dh.one(['id', 'should_num'], {'id': inventory_id, 'shop_id': shop_id, 'add_user': cashier_id})
            db_inventory_id = db_inventory.get('id', 0)
            if db_inventory_id == 0:
                return error('盘点数据不存在')
            update_data = {'step': step}
            if step in [2, 3]:
                update_data.update({'status': 1})
            goods_total = db_inventory.get('should_num')
            inventory_stats_data = inventory.get_inventory_stats_data(cursor, inventory_id, goods_total)
            update_data.update(inventory_stats_data)
            dh.update(update_data, {'id': db_inventory_id})
    except Exception as e:
        err = '提交盘点异常'
        print(err, e)
        return error(err)
    return success()


@jwt_auth
def cancel_inventory(request, auth):
    try:
        form = RawJsonForm(request.body)
        shop_id = auth.get('shop_id')
        cashier_id = auth.get('cashier_id')
        inventory_ids = form.get('ids')
        if inventory_ids == "":
            return error('无效的盘点ID')
        id_arr = str_helper.split_id_str(inventory_ids)
        if len(id_arr) == 0:
            return error('无效的盘点ID')
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            id_in_filter = 'id in ({})'.format(','.join(id_arr))
            dh.update({'status': 5}, {id_in_filter: None, 'status': 0, 'shop_id': shop_id, 'add_user': cashier_id})
            dh = DB('table_inventory_detail', conn=cursor)
            iid_in_filter = 'i_id in ({})'.format(','.join(id_arr))
            dh.update({'round_sn': ''}, {iid_in_filter: None})
    except Exception as e:
        err = '作废盘点异常'
        print(err, e)
        return error(err)
    return success()


@jwt_auth
def inventory_progress(request, auth):
    try:
        form = RawJsonForm(request.body)
        inventory_id = form.get_int('id')
        flag = form.get_int('flag', None)
        if inventory_id == 0:
            return error('无效的盘点ID')
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            inventory_fields = ['id', 'sto_typ', 'shop_id', 'w_id']
            db_inventory = dh.one(inventory_fields, {'id': inventory_id})
            db_inventory_id = db_inventory.get('id', 0)
            if db_inventory_id == 0:
                return error('盘点不存在')
            db_inventory_sto_typ = db_inventory.get('sto_typ')
            binds = [inventory_id]
            if db_inventory_sto_typ == 2:
                sql = 'SELECT tid.id,g.c_id class_id,COUNT(*) num FROM table_warehouse_goods g'
                sql_frag = ' GROUP BY g.c_id'
                sql_frag_arr = ['g.w_id=%s']
                db_inventory_w_id = db_inventory.get('w_id')
                binds.append(db_inventory_w_id)
            else:
                sql = 'SELECT tid.id,g.class_id,COUNT(*) num FROM table_goods g'
                sql_frag = ' GROUP BY g.class_id'
                sql_frag_arr = ['g.shoper_id=%s']
                db_inventory_shop_id = db_inventory.get('shop_id')
                binds.append(db_inventory_shop_id)
            sql += ' LEFT JOIN table_inventory_detail tid ON tid.good_id=g.id AND tid.i_id=%s'

            if flag is not None:
                if flag == 0:
                    sql_frag_arr.append('tid.id is NULL')
                elif flag == 1:
                    sql_frag_arr.append('tid.id is not NULL')
                elif flag == 2:
                    sql_frag_arr.append('tid.state=0')
                elif flag == 3:
                    sql_frag_arr.append('tid.state=1')
                elif flag == 4:
                    sql_frag_arr.append('tid.state=2')

            sql += ' WHERE ' + ' AND '.join(sql_frag_arr)
            sql += sql_frag
            rows = dh.query(sql, binds)
            class_id_arr = []
            for row in rows:
                class_id_arr.append(str(row.get('class_id')))
            class_ids = ','.join(class_id_arr)
            if db_inventory_sto_typ == 2:
                class_dict = warehouse.query_warehouse_goods_class_dict_by_ids(cursor, class_ids)
            else:
                class_dict = goods_class.query_class_dict_by_ids(cursor, class_ids)
            for row in rows:
                class_id = row.get('class_id')
                class_name = class_dict.get(class_id, '未分类')
                row.update({'class_name': class_name})
    except Exception as e:
        err = '异常'
        print(err, e)
        return error(err)
    return success(rows)


@jwt_auth
def update_inventory_stats_data(request, auth):
    try:
        form = RawJsonForm(request.body)
        shop_id = auth.get('shop_id')
        cashier_id = auth.get('cashier_id')
        inventory_id = form.get_int('id')
        if inventory_id == 0:
            return error('无效的盘点ID')
        with connection.cursor() as cursor:
            dh = DB('table_inventory', conn=cursor)
            db_inventory = dh.one(['id', 'should_num'], {'id': inventory_id, 'shop_id': shop_id, 'add_user': cashier_id})
            db_inventory_id = db_inventory.get('id', 0)
            if db_inventory_id == 0:
                return error('盘点不存在')
            goods_total = db_inventory.get('should_num')
            update_data = inventory.get_inventory_stats_data(cursor, inventory_id, goods_total)
            dh.update(update_data, {'id': db_inventory_id})
    except Exception as e:
        err = '异常'
        print(err, e)
        return error(err)
    return success()


@jwt_auth
def stats_inventory_goods(request, auth):
    try:
        form = RawJsonForm(request.body)
        inventory_id = form.get_int('id')
        if inventory_id == 0:
            return error('无效的盘点ID')
        with connection.cursor() as cursor:
            stats_num, stats_amount = inventory.stats_inventory_detail_goods_num_and_amount(cursor, inventory_id)
            data = {
                'ctg_num': inventory.count_inventory_detail_by_inventory_id(cursor, inventory_id),
                'total_num': stats_num,
                'total_amount': stats_amount
            }
    except Exception as e:
        err = '异常'
        print(err, e)
        return error(err)
    return success(data)
